//
//  UIControl+GAClickInterval.m
//  Gunterapple
//
//  Created by 热带雨林 on 2021/1/25.
//  Copyright © 2021 热带雨林. All rights reserved.
//

#import "UIControl+GAClickInterval.h"
#import <objc/runtime.h>

//默认时间间隔
static double kDefaultInterval = 0.5;

@interface UIControl ()

//是否可以点击
@property (nonatomic, assign) BOOL isIgnoreClick;
//上次按钮响应的方法名
@property (nonatomic, strong) NSString *oldSELName;

@end

@implementation UIControl (GAClickInterval)
+ (void)ga_exchangeClickMethod{
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        SEL originSel = @selector(sendAction:to:forEvent:);
        SEL newSel = @selector(ga_snedClickIntervalAction:to:forEvent:);
        
        Method originSelMethod = class_getInstanceMethod(self, originSel);
        Method newSelMethod = class_getInstanceMethod(self, newSel);
        
        BOOL isAddNewMethod = class_addMethod(self, originSel, method_getImplementation(newSelMethod), "V@:");
        if(isAddNewMethod){
            class_replaceMethod(self, newSel, method_getImplementation(originSelMethod), "V@:");
        }else{
            method_exchangeImplementations(originSelMethod, newSelMethod);
        }
    });
}

//替换的方法
- (void)ga_snedClickIntervalAction:(SEL)action to:(id)target forEvent:(UIEvent *)event{
    NSLog(@"替换点击方法");
    //点击的是按钮 并且 不忽略时间间隔 
    if([self isKindOfClass:[UIButton class]] && !self.ignoreClickInterval){
//        NSLog(@"+++++++%s",__FUNCTION__);
        //如果时间间隔小于等于0 将时间间隔设置为默认时间间隔
        if(self.clickInterval <= 0)
            self.isIgnoreClick = kDefaultInterval;
        
        //获取当前方法名称
        NSString *currentSELName = NSStringFromSelector(action);
        /**
         1.第一次点击获得当前方法名称   旧方法名称为nil   self.isIgnoreClick 为 NO 继续执行
         2.在设置的间隔时间内 多次点击 根据判断条件直接 return 点击方法不执行
         3.外部设置了间隔时间大于0  self.isIgnoreClick置为YES 之后执行延时方法 根据设置的延时时间 间隔时间完毕之后将旧方法名称置为nil  条件不成立 点击方法执行
         */
        if(self.isIgnoreClick && [self.oldSELName isEqualToString:currentSELName]){
            return;
        }
        //设置了时间间隔
        if(self.clickInterval > 0){
            self.isIgnoreClick = YES;
            self.oldSELName = currentSELName;
            [self performSelector:@selector(ga_ignoreClickState:) withObject:nil afterDelay:self.clickInterval];
        }
    }
    [self ga_snedClickIntervalAction:action to:target forEvent:event];
}

//延时方法 间隔时间走完之后，将self.oldSELName置为nil
- (void)ga_ignoreClickState:(NSNumber *)ignoreClickState{
    self.isIgnoreClick = ignoreClickState.boolValue;
    self.oldSELName = @"";
}


//通过关联对象实现分类属性set get 方法
//时间间隔
- (NSTimeInterval)clickInterval{
    return [objc_getAssociatedObject(self, _cmd) doubleValue];
}
- (void)setClickInterval:(NSTimeInterval)clickInterval{
    /**
     id object：被关联的对象
     const void *key：关联的key，要求唯一
     id value：关联的对象
     objc_AssociationPolicy policy：内存管理的策略
     */
    objc_setAssociatedObject(self, @selector(clickInterval), @(clickInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

//是否可以点击
- (BOOL)isIgnoreClick{
    return [objc_getAssociatedObject(self, _cmd) boolValue];
}
- (void)setIsIgnoreClick:(BOOL)isIgnoreClick{
    objc_setAssociatedObject(self, @selector(isIgnoreClick), @(isIgnoreClick), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

//是否忽略响应时间间隔
- (BOOL)ignoreClickInterval{
    return [objc_getAssociatedObject(self, _cmd) boolValue];
}
- (void)setIgnoreClickInterval:(BOOL)ignoreClickInterval{
    objc_setAssociatedObject(self, @selector(ignoreClickInterval), @(ignoreClickInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

//上次响应的方法
- (NSString *)oldSELName{
    return objc_getAssociatedObject(self, _cmd);
}
- (void)setOldSELName:(NSString *)oldSELName{
    objc_setAssociatedObject(self, @selector(oldSELName), oldSELName, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end
